package br.com.documentos.model.persistence;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.NonUniqueResultException;
import org.hibernate.SQLQuery;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

@SuppressWarnings("unchecked")
public class BaseRepository<T> extends HibernateDaoSupport {
	
	protected Class<T> getEntityClass(){
		ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
		
		return (Class<T>) type.getActualTypeArguments()[0];
	}

	public T load( Serializable id ){
		return getHibernateTemplate().load(getEntityClass(), id);
	}
	
	public List<T> loadAll(){
		return getHibernateTemplate().loadAll(getEntityClass());
	}
	
	public List<T> list( DetachedCriteria detachedCriteria ){
		return getHibernateTemplate().findByCriteria(detachedCriteria);
	}

	protected DetachedCriteria createCriteria(){
		return DetachedCriteria.forClass(getEntityClass());
	}
	
	protected T load( String nomeCampo, Serializable campo ){
		return uniqueResult(createCriteria().add( Restrictions.eq(nomeCampo, campo) ));
	}
	
	protected T loadIgnoreCase( String nomeCampo, Serializable campo ){
		return uniqueResult(createCriteria().add( Restrictions.eq(nomeCampo, campo).ignoreCase() ));
	}

	protected T uniqueResult( DetachedCriteria criteria ){
		List<T> list = getHibernateTemplate().findByCriteria(criteria);
		T result = null;
		
		if( list.size() == 1  ){
			result = list.get(0);
		}
		else if( list.size() > 1  ){
			throw new NonUniqueResultException(list.size());
		}
		
		return result;
	}

	public void save( T entity ){
		getHibernateTemplate().save(entity);
	}
	
	public void saveOrUpdate( T entity ){
		getHibernateTemplate().saveOrUpdate(entity);
	}
	
	public void saveOrUpdateAll( List<?> entities ){
		getHibernateTemplate().saveOrUpdateAll(entities);
	}
	
	public void merge( T entity ){
		getHibernateTemplate().merge(entity);
	}
	
	public void delete( Object entity ){
		getHibernateTemplate().delete(entity);
	}
	
	public void deleteAll( List<?> entities ){
		getHibernateTemplate().deleteAll(entities);
	}
	
	public SQLQuery getSqlQuery( String sql ){
		return getSession().createSQLQuery(sql);
	}
}
